using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Comteck.Dto.Goods;
using Comteck.Dto.Orders;
using Comteck.Dto.Sys;
using Comteck.Entities.Goods;
using Comteck.Entities.Orders;
using Comteck.Extensions;
using Comteck.Ktt.Services.Goods;
using Comteck.Ktt.Services.Infrastructure;
using Comteck.Ktt.Services.Plugs.EMS;
using Comteck.Ktt.Services.Sys;
using ExpressMapper.Extensions;
using Newtonsoft.Json;

namespace Comteck.Ktt.Services.Orders {
  /// <summary>
  /// 
  /// </summary>
  public class SaleOrderService : BaseKttService, ISaleOrderService {

    #region fields

    private readonly IKttRepository<SaleOrder, string> _saleOrderRepository;
    private readonly IKttRepository<SaleOrderDetail, string> _saleOrderDetailRepository;
    private readonly IKttRepository<SaleOrderPath, string> _SaleOrderPathRepository;
    private readonly Lazy<IProductService> productService;
    private readonly Lazy<ISelfOrgService> selfOrgService;
    private readonly Lazy<IParameterService> parameterService;

    #endregion

    #region ctor

    public SaleOrderService(IKttUnitOfWork unitOfWork,
      Lazy<IProductService> productService,
      Lazy<ISelfOrgService> selfOrgService,
      Lazy<IParameterService> parameterService) : base(unitOfWork) {
      _saleOrderRepository = _unitOfWork.GetRepository<SaleOrder, string>();
      _saleOrderDetailRepository = _unitOfWork.GetRepository<SaleOrderDetail, string>();
      _SaleOrderPathRepository = _unitOfWork.GetRepository<SaleOrderPath, string>();
      this.productService = productService;
      this.selfOrgService = selfOrgService;
      this.parameterService = parameterService;
    }

    #endregion

    #region 更新订单

    /// <summary>
    /// 更新订单
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    public async Task<AjaxResponse<SaleOrderDto>> UpdateAsync(SaleOrderDto model) {
      var result = new AjaxResponse<SaleOrderDto>();

      var order = await _saleOrderRepository.GetByIdAsync( model.Id);
      if (order == null) {
        result.Code = 0;
        result.Message = "订单不存在";
        return result;
      }

      // 更新允许编辑的字段
      order.Recipient = model.Recipient;
      order.RecipientPhone = model.RecipientPhone;
      order.RecipientAddress = model.RecipientAddress;
      order.GroupDesc = model.GroupDesc;
      order.BuyUserDesc = model.BuyUserDesc;

    await _saleOrderRepository.UpdateAsync(order);

      result.Code = 1;
      result.Data = order.MapTo<SaleOrderDto>();
      return result;
    }

    #endregion

    #region 查询分页主表数据

    /// <summary>
    /// 查询分页主表数据
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    public async Task<AjaxResponsePage<List<SaleOrderDto>>> GetPageListAsync(SaleOrderQuery model) {
      var result = new AjaxResponsePage<List<SaleOrderDto>>() {
        Size = model.Size,
        Page = model.Page,
      };

      // 查询表达式
      var query = this.GetListQuery(model);

      // search
      result.Total = await query.CountAsync();

      var list = await query.OrderBy(x => x.ImportTime)
        .ThenBy(x => x.Code)
        .Skip((Math.Max(model.Page, 1) - 1) * model.Size)
        .Take(model.Size).ToListAsync();
      result.Data = list.MapTo<List<SaleOrderDto>>();

      return result;
    }

    /// <summary>
    /// query
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    private IQueryable<SaleOrder> GetListQuery(SaleOrderQuery model) {
      var query = from d in _saleOrderRepository.TableUntracked
                  select d;

      // 结束日期
      var searchEndDate = model.Search_End_Date == null ?  (DateTime?)null : model.Search_End_Date.Value.AddDays(1);

      query = query
        .WhereIIf(model.Search_Begin_Date != null, x => x.ImportTime >= model.Search_Begin_Date)
        .WhereIIf(searchEndDate != null, x => x.ImportTime < searchEndDate)
        .WhereIIf(model.StatusList != null, x => model.StatusList.Contains(x.Status))
        .WhereIIf(model.SelfOrgIdList != null, x => model.SelfOrgIdList.Contains(x.SelfOrgId))
        .WhereIIf(model.Code.IsNotNullOrEmpty(), x => x.Code == model.Code || x.MainCode == model.Code)
        .WhereIIf(model.GroupNumber.IsNotNullOrEmpty(), x => x.GroupNumber == model.GroupNumber || x.MainGroupNumber == model.GroupNumber)
        .WhereIIf(model.DeliveryCode.IsNotNullOrEmpty(), x => x.DeliveryCode == model.DeliveryCode);

      return query;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    private async Task<IEnumerable<SaleOrder>> GetOrderListByIdsAsync(List<string> ids) {
      return await _saleOrderRepository.FindAsync(x => ids.Contains(x.Id));
    }

    #endregion

    #region 商品订单明细

    /// <summary>
    /// 商品订单明细
    /// </summary>
    /// <param name="orderId"></param>
    /// <returns></returns>
    public async Task<IEnumerable<SaleOrderDetailDto>> GetDetailListByOrderIdAsync(string orderId) {
      var list = await _saleOrderDetailRepository.FindAsync(x => x.OrderId == orderId);
      return list.OrderBy(x => x.SeqNo).ThenBy(x => x.ProductId).MapTo<List<SaleOrderDetailDto>>();
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    private async Task<IEnumerable<SaleOrderDetail>> GetDetailListByIdsAsync(List<string> ids) {
      return await _saleOrderDetailRepository.FindAsync(x => ids.Contains(x.OrderId));
    }

    #endregion

    #region 订单轨迹明细

    /// <summary>
    /// 
    /// </summary>
    /// <param name="orderId"></param>
    /// <returns></returns>
    private IQueryable<SaleOrderPath> GetPathQueryableByOrderId(string orderId) {
      return _SaleOrderPathRepository.TableUntracked.Where(x => x.OrderId == orderId);
    }

    /// <summary>
    /// 订单轨迹明细
    /// </summary>
    /// <param name="orderId"></param>
    /// <returns></returns>
    public async Task<IEnumerable<SaleOrderPathDto>> GetPathListByOrderIdAsync(string orderId) {
      var query = this.GetPathQueryableByOrderId(orderId);
      return (await query.OrderBy(x => x.OpTime).ToListAsync()).MapTo<List<SaleOrderPathDto>>();
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    private async Task<IEnumerable<SaleOrderPath>> GetPathListByIdsAsync(List<string> ids) {
      return await _SaleOrderPathRepository.FindAsync(x => ids.Contains(x.OrderId));
    }

    #endregion

    #region 转换excel

    /// <summary>
    /// 转换excel
    /// </summary>
    /// <param name="table"></param>
    /// <returns></returns>
    public async Task<List<SaleOrderExcelDto>> ChangeExcelDataAsync(DataTable table) {
      var result = new List<SaleOrderExcelDto>();

      // 总列数
      var columnNum = table.Columns.Count;
      var tableColumnList = new List<string>();
      foreach (DataColumn column in table.Columns) {
        tableColumnList.Add(column.Caption);
      }

      var startIndex = 7;
      var endIndex = tableColumnList.FindIndex(x => x == "商品种类数");

      // 循环
      var loopIndex = 0;

      // 循环行，一行为一个订单
      foreach (DataRow row in table.Rows) {
        var orderDto = new SaleOrderExcelDto() {
          // 1-7列为订单列
          GroupNumber = row[0].To<string>(),
          Code = row[1].To<string>(),
          GroupTitle = row[2].To<string>(),
          BuyUserName = row[3].To<string>(),
          BuyUserDesc = row[4].To<string>(),
          PayDate = row[5].To<DateTime?>(),
          GroupDesc = row[6].To<string>(),
          // 中间为商品列
          // 【商品种类数】及以后为订单列
          GoodsCount = row[endIndex].To<int>(),
          GoodsAmt = row[endIndex + 1].To<decimal>(),
          FreightAmt = row[endIndex + 2].To<decimal>(),
          DiscountAmt = row[endIndex + 3].To<decimal>(),
          TotalAmt = row[endIndex + 4].To<decimal>(),
          ReturnAmt = row[endIndex + 5].To<decimal>(),
          StatusName = row[endIndex + 6].To<string>(),
          GroupName = row[endIndex + 7].To<string>(),
          DeliveryTypeName = row[endIndex + 8].To<string>(),
          SelfOrgName = RemoveParenthesesContent(row[endIndex + 9].To<string>()),
          SelfOrgContacts = row[endIndex + 10].To<string>(),
          SelfOrgPhone = row[endIndex + 11].To<string>(),
          SelfOrgAddress = row[endIndex + 12].To<string>(),

          Recipient = row[endIndex + 13].To<string>(),
          RecipientPhone = row[endIndex + 14].To<string>(),
          Province = row[endIndex + 15].To<string>(),
          City = row[endIndex + 16].To<string>(),
          District = row[endIndex + 17].To<string>(),
          RecipientAddress = row[endIndex + 18].To<string>(),

          SeqNo = ++loopIndex,

          DetailList = new List<SaleOrderDetailExcelDto>()
        };

        // 去除回车换行
        if (orderDto.RecipientAddress.IsNotNullOrEmpty()) {
          orderDto.RecipientAddress = orderDto.RecipientAddress.Replace("\r", string.Empty).Replace("\n", string.Empty);
        }
        if (orderDto.SelfOrgAddress.IsNotNullOrEmpty()) {
          orderDto.SelfOrgAddress = orderDto.SelfOrgAddress.Replace("\r", string.Empty).Replace("\n", string.Empty);
        }

        // 商品列
        var subLoopIndex = 0;
        for (var i = startIndex; i < endIndex; i++) {
          var qty = row[i].To<int>();
          if (qty > 0) {
            orderDto.DetailList.Add(new SaleOrderDetailExcelDto() {
              ProductId = 0,
              ProductName = tableColumnList[i],
              SeqNo = ++subLoopIndex,
              Qty = qty,
              Weight = decimal.Zero,
              TotalWeight = decimal.Zero,
            });
          }
        }

        // add
        result.Add(orderDto);
      }

      // 处理订单的主信息
      await this.HandleCommonCheckForChangeExcelDataAsync(result);

      // 处理自提点
      await this.HandleSelfOrgForChangeExcelDataAsync(result);

      // 处理商品档案
      await this.HandleProductForChangeExcelDataAsync(result);

      return result;
    }

    /// <summary>
    /// 处理订单的主信息
    /// </summary>
    /// <param name="list"></param>
    /// <returns></returns>
    private async Task HandleCommonCheckForChangeExcelDataAsync(List<SaleOrderExcelDto> list) {
      // 查询全部订单
      var orderCodeList = list.Where(x => x.Code.IsNotNullOrEmpty()).Select(x => x.Code).ToList();
      var orderList = orderCodeList.IsNullOrEmpty() ? new List<string>() : await _saleOrderRepository.TableUntracked.Where(x => orderCodeList.Contains(x.Code)).Select(x => x.Code).ToListAsync();

      // check
      foreach (var row in list) {
        if (orderList.Contains(row.Code)) {
          row.IsValid = false;
          row.SetError("订单已存在");
        }
      }
    }

    /// <summary>
    /// 处理自提点信息
    /// </summary>
    /// <param name="list"></param>
    /// <returns></returns>
    private async Task HandleSelfOrgForChangeExcelDataAsync(List<SaleOrderExcelDto> list) {
      // 查询现在全部的自提点
      var allSelfOrgList = (await selfOrgService.Value.GetAllAsync()).ToList();
      var allSelfOrgRelationList = (await selfOrgService.Value.GetAllRelationAsync()).ToLookup(x => x.SelfOrgId);

      // 现在需要增加的自提点
      var exceptNames = list.Where(x => !allSelfOrgList.Any(y => y.Name == x.SelfOrgName)).Select(x => x.SelfOrgName).Distinct().ToList();
      if (exceptNames.IsNotNullOrEmpty()) {
        var dataDic = list.ToLookup(x => x.SelfOrgName);

        var addList = exceptNames
          .Select(x => dataDic[x].FirstOrDefault())
          .Select(x => new SelfOrg() {
            Id = 0,
            Name = x.SelfOrgName,
            Contacts = x.SelfOrgContacts,
            Phone = x.SelfOrgPhone,
            Address = x.SelfOrgAddress,
            Recipient = x.Recipient,
            RecipientPhone = x.RecipientPhone,
            Province = x.Province,
            City = x.City,
            District = x.District,
            Street = null,
            RecipientAddress = x.RecipientAddress,
            CreateTime = DateTime.Now
          })
          .ToList();
        await selfOrgService.Value.InsertBatchAsync(addList);
        allSelfOrgList.AddRange(addList.MapTo<List<SelfOrgDto>>());
      }
      var allSelfOrgDic = allSelfOrgList.ToLookup(x => x.Name);

      // 赋值自提点
      foreach (var row in list) {
        var dbRow = allSelfOrgDic[row.SelfOrgName].FirstOrDefault();
        if (dbRow != null) {
          row.SelfOrgId = dbRow.Id;
          row.SelfOrgTagIdExists = allSelfOrgRelationList[dbRow.Id].Any();
        } else {
          row.IsValid = false;
          row.SetError("自提点不存在");
        }
      }
    }

    /// <summary>
    /// 处理商品档案
    /// </summary>
    /// <param name="list"></param>
    /// <returns></returns>
    private async Task HandleProductForChangeExcelDataAsync(List<SaleOrderExcelDto> list) {
      // 查询现在全部的自提点
      var allProductList = (await productService.Value.GetAllAsync()).ToList();

      // 现在需要增加的自提点
      var allDetailList = list.SelectMany(x => x.DetailList);
      var exceptNames = allDetailList.Where(x => !allProductList.Any(y => y.Name == x.ProductName)).Select(x => x.ProductName).Distinct().ToList();
      if (exceptNames.IsNotNullOrEmpty()) {
        var dataDic = allDetailList.ToLookup(x => x.ProductName);

        var addList = exceptNames
          .Select(x => dataDic[x].FirstOrDefault())
          .Select(x => new Product() {
            Id = 0,
            Code = null,
            Name = x.ProductName,
            Weight = decimal.Zero,
            Description = null,
            CreateTime = DateTime.Now
          })
          .ToList();
        await productService.Value.InsertBatchAsync(addList);
        allProductList.AddRange(addList.MapTo<IEnumerable<ProductDto>>());
      }
      var allProductDic = allProductList.ToLookup(x => x.Name);

      // 赋值
      foreach (var row in allDetailList) {
        var dbRow = allProductDic[row.ProductName].FirstOrDefault();
        if (dbRow != null) {
          row.ProductId = dbRow.Id;
          row.Weight = dbRow.Weight;
          row.TotalWeight = row.Weight * row.Qty;
          row.WeightExist = dbRow.Weight > decimal.Zero;
        } else {
          row.IsValid = false;
          row.SetError($"[{row.ProductName}]档案不存在");
        }
      }

      // 计算总重量
      list.ForEach(x => {
        x.GoodsWeight = x.DetailList.Sum(y => y.TotalWeight);
      });
    }

    #endregion

    #region 填充商品重量信息

    /// <summary>
    /// 填充商品重量信息
    /// </summary>
    /// <param name="list"></param>
    /// <returns></returns>
    public async Task<List<SaleOrderExcelDto>> FillProductInfoForExcelDataAsync(List<SaleOrderExcelDto> list) {
      if (list.IsNullOrEmpty()) {
        return list;
      }

      // 查找重量为0的商品id
      var productIdList = list.SelectMany(x => x.DetailList).Where(x => x.Weight <= decimal.Zero).Select(x => x.ProductId).Distinct().ToList();
      var productDic = (await productService.Value.GetListByIdsAsync(productIdList)).ToLookup(x => x.Id);

      foreach (var row in list) {
        foreach (var detail in row.DetailList) {
          var product = productDic[detail.ProductId].FirstOrDefault();
          if (product != null) {
            detail.Weight = product.Weight;
            detail.TotalWeight = detail.Weight * detail.Qty;
          }
        }

        row.GoodsWeight = row.DetailList.Sum(x => x.TotalWeight);
      }

      return list;
    }

    #endregion

    #region 保存excel

    /// <summary>
    /// 保存多个对象
    /// </summary>
    /// <param name="modelList"></param>
    /// <param name="user"></param>
    /// <returns></returns>
    public async Task<List<SaleOrderDto>> SaveExcelDataAsync(List<SaleOrderExcelDto> modelList) {
      // data
      var mainList = new List<SaleOrder>();
      var detailList = new List<SaleOrderDetail>();

      // 导入批次号
      var importBatchNo = BitConverter.ToInt64(Guid.NewGuid().ToByteArray(), 0).ToString();
      var importTime = DateTime.Now;

      // 循环
      foreach (var row in modelList) {
        var order = row.MapTo<SaleOrder>();
        order.Id = Guid.NewGuid().ToString();
        order.Status = (int) EnumSaleOrderStatus.未审核;
        order.ImportBatchNo = importBatchNo;
        order.ImportTime = importTime;

        // 主单标识
        order.MainOrderFlag = (int) EnumMainOrderFlag.正常;
        order.MainCode = order.Code;
        order.MainGroupNumber = order.GroupNumber;
        order.MainSplitCount = 1; // 订单数

        var subDetailList = row.DetailList.MapTo<List<SaleOrderDetail>>();
        subDetailList.ForEach(x => {
          x.Id = Guid.NewGuid().ToString();
          x.OrderId = order.Id;
          x.GroupDetailId = x.Id;
        });

        order.GoodsWeight = subDetailList.Sum(x => x.TotalWeight);

        mainList.Add(order);
        detailList.AddRange(subDetailList);
      }

      try {
        // insert
        _unitOfWork.BeginTransaction();
        await _saleOrderRepository.AddRangeAsync(mainList);
        await _saleOrderDetailRepository.AddRangeAsync(detailList);
        await _unitOfWork.CommitTransactionAsync();
      } catch {
        _unitOfWork.RollbackTransaction();
        throw;
      }

      return mainList.MapTo<List<SaleOrderDto>>();
    }

    #endregion

    #region 批量删除订单

    /// <summary>
    /// 批量删除订单
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    public async Task DeleteBatchAsync(List<string> ids) {
      // 查询主表
      var orderList = await this.GetOrderListByIdsAsync(ids);
      var detailList = await this.GetDetailListByIdsAsync(ids);
      var pathList = await this.GetPathListByIdsAsync(ids);

      if (orderList.Any(x => x.Status != (int) EnumSaleOrderStatus.已删除)) {
        throw new ComteckException($"请选择 {EnumSaleOrderStatus.已删除} 的记录");
      }

      // 已生成子单的主单不允许删除
      if (orderList.Any(x => x.MainOrderFlag == (int) EnumMainOrderFlag.已拆单)) {
        throw new ComteckException($"{EnumMainOrderFlag.已拆单}的订单不允许删除");
      }

      // 子单不允许删除
      if (orderList.Any(x => x.MainOrderFlag == (int) EnumMainOrderFlag.子单)) {
        throw new ComteckException($"{EnumMainOrderFlag.子单}不允许删除");
      }

      try {
        _unitOfWork.BeginTransaction();
        await _saleOrderRepository.RemoveRangeAsync(orderList);
        await _saleOrderDetailRepository.RemoveRangeAsync(detailList);
        await _SaleOrderPathRepository.RemoveRangeAsync(pathList);
        await _unitOfWork.CommitTransactionAsync();
      } catch {
        _unitOfWork.RollbackTransaction();
        throw;
      }
    }

    #endregion

    #region 审核、强制审核、反审核、反打印

    /// <summary>
    /// 批量审核
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    public async Task<AjaxResponse<List<SaleOrderDto>>> AuditBatchAsync(List<string> ids) {
      return await this.UpdateStatusBatchAsync(ids, EnumSaleOrderStatus.已审核);
    }

    /// <summary>
    /// 批量强制审核
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    public async Task<AjaxResponse<List<SaleOrderDto>>> ForceAuditBatchAsync(List<string> ids) {
      return await this.UpdateStatusBatchAsync(ids, EnumSaleOrderStatus.已审核, true);
    }

    /// <summary>
    /// 批量反审核
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    public async Task<AjaxResponse<List<SaleOrderDto>>> UnAuditBatchAsync(List<string> ids) {
      return await this.UpdateStatusBatchAsync(ids, EnumSaleOrderStatus.未审核);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="ids"></param>
    /// <param name="status"></param>
    /// <returns></returns>
    private async Task<AjaxResponse<List<SaleOrderDto>>> UpdateStatusBatchAsync(List<string> ids, EnumSaleOrderStatus status, bool isForceAudit = false) {
      var result = new AjaxResponse<List<SaleOrderDto>>() {
        Code = 0
      };

      var orderList = await this.GetOrderListByIdsAsync(ids);

      switch (status) {
        case EnumSaleOrderStatus.未审核:
          if (orderList.Any(x => !EnumSaleOrderStatusList.已审核.Contains(x.Status))) {
            result.Message = $"请选择 {EnumSaleOrderStatus.已审核} 的记录";
            return result;
          }
          break;
        case EnumSaleOrderStatus.已审核:
          if (orderList.Any(x => !EnumSaleOrderStatusList.未审核.Contains(x.Status))) {
            result.Message = $"请选择 {EnumSaleOrderStatus.未审核} 的记录";
            return result;
          }

          // 限重
          if (!isForceAudit) {
            var order_weight = (await parameterService.Value.GetValueAsync(EnumParameter.order_weight)).To<decimal>();
            var overOderWeightCount = orderList.Count(x => x.GoodsWeight > order_weight);
            if (overOderWeightCount > 0) {
              result.Message = $"共有 {overOderWeightCount} 个订单的商品重量超过限制重量 {order_weight}，请使用【强制审核】";
              return result;
            }
          }
          break;
        case EnumSaleOrderStatus.已打印:
          if (orderList.Any(x => !EnumSaleOrderStatusList.已审核.Contains(x.Status))) {
            result.Message = $"请选择 {EnumSaleOrderStatus.已审核} 的记录";
            return result;
          }
          break;
        default:
          break;
      }

      // update
      foreach (var row in orderList) {
        row.Status = (int) status;
      }
      await _saleOrderRepository.UpdateRangeAsync(orderList);

      // return
      result.Code = 1;
      result.Data = orderList.MapTo<List<SaleOrderDto>>();
      return result;
    }

    #endregion

    #region 将多个商品拆分到新订单上

    /// <summary>
    /// 将多个商品拆分到新订单上
    /// </summary>
    /// <param name="orderId"></param>
    /// <param name="detailIds"></param>
    /// <returns></returns>
    public async Task<AjaxResponse<SaleOrderSplitGoods2NewOrder>> SplitGoods2NewOrderAsync(string orderId, List<string> detailIds) {
      var result = new AjaxResponse<SaleOrderSplitGoods2NewOrder>() {
        Code = 0
      };

      var mainOrder = await _saleOrderRepository.GetByIdAsync(orderId);
      if (mainOrder == null) {
        result.Message = "该订单不存在";
        return result;
      }
      if (mainOrder.MainOrderFlag == (int) EnumMainOrderFlag.子单) {
        result.Message = "子单不允许拆单";
        return result;
      }

      // 查询主单信息
      var mainOrderDetails = await this.GetDetailListByOrderIdAsync(orderId);
      if (mainOrderDetails.Count() == detailIds.Count) {
        result.Message = "不能将所有商品都拆分到新订单上";
        return result;
      }

      // 原先的子单数量
      var beforeCount = mainOrder.MainSplitCount;

      // 创建新订单
      var newOrder = mainOrder.MapTo<SaleOrder>();
      newOrder.Id = Guid.NewGuid().ToString();
      newOrder.Status = mainOrder.Status;
      newOrder.ImportBatchNo = mainOrder.ImportBatchNo;
      newOrder.ImportTime = mainOrder.ImportTime;
      newOrder.DeliveryCode = null;
      newOrder.MainOrderFlag = (int) EnumMainOrderFlag.子单;
      newOrder.GroupNumber = $"{mainOrder.MainGroupNumber}-{(beforeCount + 1):D3}";
      newOrder.Code = $"{mainOrder.MainCode}-{(beforeCount + 1):D3}";
      newOrder.GoodsCount = detailIds.Count;

      // 新订单商品
      var newOrderDetail = mainOrderDetails.Where(x => detailIds.Contains(x.Id)).MapTo<List<SaleOrderDetail>>();
      newOrderDetail.ForEach(x => {
        x.Id = Guid.NewGuid().ToString();
        x.OrderId = newOrder.Id;
      });
      newOrder.GoodsWeight = newOrderDetail.Sum(x => x.TotalWeight);

      // 主表
      var deleteDetailList = mainOrderDetails.Where(x => detailIds.Contains(x.Id)).MapTo<List<SaleOrderDetail>>();
      mainOrderDetails = mainOrderDetails.Where(x => !detailIds.Contains(x.Id)).ToList();

      mainOrder.GoodsWeight = mainOrderDetails.Where(x => x.OrderId == mainOrder.Id).Sum(x => x.TotalWeight);
      mainOrder.GoodsCount = mainOrderDetails.Count(x => x.OrderId == mainOrder.Id);
      mainOrder.Code = $"{mainOrder.MainCode}-001";
      mainOrder.GroupNumber = $"{mainOrder.MainGroupNumber}-001";
      mainOrder.MainSplitCount = beforeCount + 1;
      mainOrder.MainOrderFlag = (int) EnumMainOrderFlag.已拆单;

      // 查询其他的子单
      var historyOrderList = (await _saleOrderRepository.FindAsync(x => x.MainCode == mainOrder.MainCode && x.MainOrderFlag == (int) EnumMainOrderFlag.子单)).ToList();
      historyOrderList.ForEach(x => x.MainSplitCount = mainOrder.MainSplitCount);

      try {
        _unitOfWork.BeginTransaction();

        // 更新主订单
        await _saleOrderRepository.UpdateAsync(mainOrder);
        await _saleOrderDetailRepository.RemoveRangeAsync(deleteDetailList);

        // 更新其他从订单
        await _saleOrderRepository.UpdateRangeAsync(historyOrderList);

        // 新增从订单
        await _saleOrderRepository.AddAsync(newOrder);
        await _saleOrderDetailRepository.AddRangeAsync(newOrderDetail);

        await _unitOfWork.CommitTransactionAsync();
      } catch {
        _unitOfWork.RollbackTransaction();
        throw;
      }

      // return
      result.Data = new SaleOrderSplitGoods2NewOrder() {
        MainOrder = mainOrder.MapTo<SaleOrderDto>(),
        NewOrder = newOrder.MapTo<SaleOrderDto>(),
      };
      result.Code = 1;
      return result;
    }

    #endregion

    #region 把订单明细商品拆分成多个订单

    /// <summary>
    /// 把订单明细商品拆分成多个订单
    /// </summary>
    /// <param name="detailId"></param>
    /// <param name="newQty">每份数量</param>
    /// <returns></returns>
    public async Task<AjaxResponse<List<SaleOrderDto>>> SplitOrderDetailAsync(string orderId, string detailId, int newQty) {
      var result = new AjaxResponse<List<SaleOrderDto>>() {
        Code = 0
      };

      var mainOrder = await _saleOrderRepository.GetByIdAsync(orderId);
      if (mainOrder == null) {
        result.Message = "该订单不存在";
        return result;
      }
      if (mainOrder.MainOrderFlag == (int) EnumMainOrderFlag.子单) {
        result.Message = "子单不允许拆单";
        return result;
      }

      if (!EnumSaleOrderStatusList.未审核.Contains(mainOrder.Status)) {
        result.Message = $"请选择 {EnumSaleOrderStatus.未审核} 的记录";
        return result;
      }

      // 查询订单信息
      var mainOrderDetails = await this.GetDetailListByOrderIdAsync(orderId);
      var mainOrderDetail = mainOrderDetails.FirstOrDefault(x => x.Id == detailId);
      if (mainOrderDetail == null) {
        result.Message = "该订单商品不存在";
        return result;
      }
      var hasMoreDetail = mainOrderDetails.Count() > 1;

      // 每份总重量
      var totalWeight = newQty * mainOrderDetail.Weight;

      // 订单数
      var orderCount = (int) Math.Ceiling((double) mainOrderDetail.Qty / newQty);

      if (orderCount <= 1) {
        result.Message = $"该订单不需要拆成1单";
        return result;
      }

      // 最后一条的数量
      var lastQty = mainOrderDetail.Qty - (orderCount - 1) * newQty;

      var orderList = new List<SaleOrder>();
      var orderDetailList = new List<SaleOrderDetail>();

      // 原先的子单数量
      var beforeCount = mainOrder.MainSplitCount;

      // loop
      for (var i = 1; i <= orderCount; i++) {
        // 第一条做特殊处理，为当前主订单
        if (i == 1) {
          // 明细
          mainOrderDetail.Qty = newQty;
          mainOrderDetail.TotalWeight = newQty * mainOrderDetail.Weight;
          // 主表
          mainOrder.GoodsWeight = mainOrderDetails.Sum(x => x.TotalWeight);
          mainOrder.Code = $"{mainOrder.MainCode}-001";
          mainOrder.GroupNumber = $"{mainOrder.MainGroupNumber}-001";
          mainOrder.MainSplitCount = orderCount + beforeCount -1;
          mainOrder.MainOrderFlag = (int) EnumMainOrderFlag.已拆单;
          continue;
        }

        // 子单
        var subOrder = mainOrder.MapTo<SaleOrder>();
        subOrder.Id = Guid.NewGuid().ToString();
        subOrder.Status = mainOrder.Status;
        subOrder.ImportBatchNo = mainOrder.ImportBatchNo;
        subOrder.ImportTime = mainOrder.ImportTime;
        subOrder.DeliveryCode = null;
        subOrder.MainOrderFlag = (int) EnumMainOrderFlag.子单;
        subOrder.GroupNumber = $"{mainOrder.MainGroupNumber}-{(i + beforeCount - 1):D3}";
        subOrder.Code = $"{mainOrder.MainCode}-{(i + beforeCount - 1):D3}";
        subOrder.GoodsCount = 1;

        var subOrderDetail = mainOrderDetail.MapTo<SaleOrderDetail>();
        subOrderDetail.Id = Guid.NewGuid().ToString();
        subOrderDetail.OrderId = subOrder.Id;
        subOrderDetail.Qty = i == orderCount ? lastQty : newQty;
        subOrderDetail.TotalWeight = subOrderDetail.Qty * mainOrderDetail.Weight;

        subOrder.GoodsWeight = subOrderDetail.TotalWeight;

        orderList.Add(subOrder);
        orderDetailList.Add(subOrderDetail);
      }

      // 查询其他的子单
      var historyOrderList = (await _saleOrderRepository.FindAsync(x => x.MainCode == mainOrder.MainCode && x.MainOrderFlag == (int) EnumMainOrderFlag.子单)).ToList();
      historyOrderList.ForEach(x => x.MainSplitCount = mainOrder.MainSplitCount);

      try {
        _unitOfWork.BeginTransaction();

        // 更新主订单
        await _saleOrderRepository.UpdateAsync(mainOrder);
        await _saleOrderDetailRepository.UpdateAsync(mainOrderDetail.MapTo<SaleOrderDetail>());

        // 更新其他从订单
        await _saleOrderRepository.UpdateRangeAsync(historyOrderList);

        // 新增从订单
        await _saleOrderRepository.AddRangeAsync(orderList);
        await _saleOrderDetailRepository.AddRangeAsync(orderDetailList);

        await _unitOfWork.CommitTransactionAsync();
      } catch {
        _unitOfWork.RollbackTransaction();
        throw;
      }

      // return
      orderList.Add(mainOrder);
      orderList.AddRange(historyOrderList);
      result.Data = orderList.MapTo<List<SaleOrderDto>>();
      result.Code = 1;
      return result;
    }

    #endregion

    #region 将已拆单的订单全部合并回来

    /// <summary>
    /// 将已拆单的订单全部合并回来
    /// </summary>
    /// <param name="orderId"></param>
    /// <returns></returns>
    public async Task<AjaxResponse<SaleOrderUnSplitDto>> CombineOrderAsync(string orderId) {
      var result = new AjaxResponse<SaleOrderUnSplitDto>() {
        Code = 0
      };

      // 查询主单
      var mainOrder = await _saleOrderRepository.GetByIdAsync(orderId);
      if (mainOrder == null) {
        result.Message = "该订单不存在";
        return result;
      }

      if (mainOrder.MainOrderFlag != (int) EnumMainOrderFlag.已拆单) {
        result.Message = $"请选择 {EnumMainOrderFlag.已拆单} 的订单";
        return result;
      }

      if (mainOrder.Status != (int) EnumSaleOrderStatus.未审核) {
        result.Message = $"请选择 {EnumSaleOrderStatus.未审核} 的记录";
        return result;
      }
      var mainDetailList = (await this.GetDetailListByIdsAsync(new List<string> { orderId })).ToList();

      // 查询子单
      var subOrderList = (await _saleOrderRepository.FindAsync(x => x.MainCode == mainOrder.MainCode && x.MainOrderFlag == (int) EnumMainOrderFlag.子单)).ToList();
      if (subOrderList.Any(x => x.Status != (int) EnumSaleOrderStatus.未审核)) {
        result.Message = $"该订单的部分子单已经被审核或者打印，请回退";
        return result;
      }

      var subOrderIdList = subOrderList.Select(x => x.Id).ToList();
      var subOrderDetailList = (await this.GetDetailListByIdsAsync(subOrderIdList)).ToList();

      // 合并明细
      var allDetailList = (from d in mainDetailList.Concat(subOrderDetailList).ToList()
                           group d by d.GroupDetailId into ds
                           select new SaleOrderDetail() {
                             Id = ds.Key,
                             OrderId = mainOrder.Id,
                             ProductId = ds.Max(x => x.ProductId),
                             ProductName = ds.Max(x => x.ProductName),
                             Qty = ds.Sum(x => x.Qty),
                             Weight = ds.Max(x => x.Weight),
                             TotalWeight = ds.Sum(x => x.Qty) * ds.Max(x => x.Weight),
                             GroupDetailId = ds.Key,
                             SeqNo = ds.Max(x => x.SeqNo),
                           }).ToList();

      // 更新主订单信息
      mainOrder.Code = mainOrder.MainCode;
      mainOrder.GroupNumber = mainOrder.MainGroupNumber;
      mainOrder.MainSplitCount = 1;
      mainOrder.MainOrderFlag = (int) EnumMainOrderFlag.正常;
      mainOrder.GoodsWeight = allDetailList.Sum(x => x.TotalWeight);
      mainOrder.GoodsCount = allDetailList.Count;
      mainOrder.DeliveryCode = null;

      try {
        _unitOfWork.BeginTransaction();

        // 更新主订单
        await _saleOrderRepository.UpdateAsync(mainOrder);
        await _saleOrderDetailRepository.RemoveRangeAsync(mainDetailList);
        await _saleOrderDetailRepository.AddRangeAsync(allDetailList);

        // 删除从订单
        await _saleOrderRepository.RemoveRangeAsync(subOrderList);
        await _saleOrderDetailRepository.RemoveRangeAsync(subOrderDetailList);

        await _unitOfWork.CommitTransactionAsync();
      } catch {
        _unitOfWork.RollbackTransaction();
        throw;
      }

      result.Data = new SaleOrderUnSplitDto() {
        MainOrder = mainOrder.MapTo<SaleOrderDto>(),
        SubOrderList = subOrderList.MapTo<List<SaleOrderDto>>(),
      };
      result.Code = 1;
      return result;
    }

    #endregion

    #region 获取运单号

    /// <summary>
    /// 获取运单号
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task<AjaxResponse<SaleOrderDto>> GetWaybillNoAsync(string id) {
      var result = new AjaxResponse<SaleOrderDto>() {
        Code = 0
      };

      // 订单主表
      var order = await _saleOrderRepository.GetByIdAsync(id);
      if (order == null) {
        result.Message = "订单不存在";
        return result;
      }
      if (order.Status == (int) EnumSaleOrderStatus.未审核) {
        result.Message = "请先将订单审核";
        return result;
      }
      var orderDto = order.MapTo<SaleOrderDto>();

      // 订单明细
      orderDto.DetailList = (await this.GetDetailListByOrderIdAsync(id)).ToList();
      if (orderDto.DetailList.IsNullOrEmpty()) {
        result.Message = "订单明细不存在";
        return result;
      }

      // ems配置信息
      var emsConfig = await parameterService.Value.GetValueAsync(EnumParameter.ems_config);
      var emsOptions = emsConfig.IsNullOrEmpty() ? null : JsonConvert.DeserializeObject<EMSClientOptions>(emsConfig);
      if (emsOptions == null || emsOptions.BaseUrl == null || emsOptions.SenderNo.IsNullOrEmpty() || emsOptions.Authorization.IsNullOrEmpty() || emsOptions.Key.IsNullOrEmpty()) {
        result.Message = "EMS配置信息不正确";
        return result;
      }

      // ems发件人
      var emsSenderConfig = await parameterService.Value.GetValueAsync(EnumParameter.ems_sender);
      var emsSender = emsSenderConfig.IsNullOrEmpty() ? null : JsonConvert.DeserializeObject<UserAddress>(emsSenderConfig);
      var emsPickUp = emsSenderConfig.IsNullOrEmpty() ? null : JsonConvert.DeserializeObject<UserAddress>(emsSenderConfig);
      if (emsSender == null) {
        result.Message = "EMS发件人配置不正确";
        return result;
      }

      // 获取面单号
      var emsResponse = await EMSHelper.GetWayBillNoAsync(orderDto, emsOptions, emsSender, emsPickUp);
      if (emsResponse.Code == 1) {
        result.Code = 1;
        orderDto.DeliveryCode = order.DeliveryCode = emsResponse.Data?.WaybillNo;
        orderDto.DeliveryStatus = (int) EnumDeliveryStatus.待揽件;
        await _saleOrderRepository.UpdateAsync(order);
        result.Data = orderDto;
      } else {
        result.Message = emsResponse.Message;
      }
      
      return result;
    }

    #endregion

    #region 获取运单号轨迹

    /// <summary>
    /// 获取运单号轨迹
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task<AjaxResponse<SaleOrderDto>> GetWaybillNoPathAsync(string id) {
      var result = new AjaxResponse<SaleOrderDto>() {
        Code = 0
      };

      // 订单主表
      var order = await _saleOrderRepository.GetByIdAsync(id);
      if (order == null) {
        result.Message = "订单不存在";
        return result;
      }
      var orderDto = order.MapTo<SaleOrderDto>();

      // ems配置信息
      var emsConfig = await parameterService.Value.GetValueAsync(EnumParameter.ems_config);
      var emsOptions = emsConfig.IsNullOrEmpty() ? null : JsonConvert.DeserializeObject<EMSClientOptions>(emsConfig);
      if (emsOptions == null || emsOptions.BaseUrl == null || emsOptions.SenderNo.IsNullOrEmpty() || emsOptions.Authorization.IsNullOrEmpty() || emsOptions.Key.IsNullOrEmpty()) {
        result.Message = "EMS配置信息不正确";
        return result;
      }

      // 获取面单号
      var emsResponse = await EMSHelper.GetWayBillNoPathAsync(new M040001Request() {
        WaybillNo = orderDto.DeliveryCode,
      }, emsOptions);
      if (emsResponse.Code == 1) {
        result.Code = 1;
        orderDto.DeliveryStatus = order.DeliveryStatus = (int) emsResponse.Data.DeliveryStatus;
        orderDto.DeliveryDesc = order.DeliveryDesc = emsResponse.Data.DeliveryDesc;

        try {
          _unitOfWork.BeginTransaction();
          await _saleOrderRepository.UpdateAsync(order);
          await this.InsertPathListAsync(id, emsResponse.Data.ResponseItems);
          await _unitOfWork.CommitTransactionAsync();
        } catch {
          _unitOfWork.RollbackTransaction();
          throw;
        }

        result.Data = orderDto;
      } else {
        result.Message = emsResponse.Message;
      }

      return result;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="orderId"></param>
    /// <param name="items"></param>
    /// <returns></returns>
    private async Task InsertPathListAsync(string orderId, List<M040001ResponseItem> items) {
      // no data
      if (items.IsNullOrEmpty()) {
        return;
      }

      // 先查询现在的轨迹
      var pathList = await this.GetPathQueryableByOrderId(orderId).ToListAsync();

      // 查询不在数据库的轨迹
      var notExistItems = items.Where(x => !pathList.Any(y => y.OpTime == x.OpTime)).ToList();
      var insertList = (from d in notExistItems
                        select new SaleOrderPath() {
                          Id = Guid.NewGuid().ToString(),
                          OrderId = orderId,
                          OpTime = d.OpTime,
                          OpCode = d.OpCode,
                          OpName = d.OpName,
                          OpDesc = d.OpDesc,
                          OpOrgProvName = d.OpOrgProvName,
                          OpOrgCity = d.OpOrgCity,
                          OpOrgCode = d.OpOrgCode,
                          OpOrgName = d.OpOrgName,
                          OperatorNo = d.OperatorNo,
                          OperatorName = d.OperatorName,
                          DeliverCode = d.DeliverCode,
                          AttemptDeliveryCode = d.AttemptDeliveryCode,
                          WaybillNo = d.WaybillNo,
                        }).ToList();
      await _SaleOrderPathRepository.AddRangeAsync(insertList);
    }

    #endregion

    #region 取消运单号

    /// <summary>
    /// 取消运单号
    /// </summary>
    /// <param name="id"></param>
    /// <param name="cancelReason"></param>
    /// <returns></returns>
    public async Task<AjaxResponse<SaleOrderDto>> CancelWaybillNoAsync(string id, string cancelReason) {
      var result = new AjaxResponse<SaleOrderDto>() {
        Code = 0
      };

      // 订单主表
      var order = await _saleOrderRepository.GetByIdAsync(id);
      if (order == null) {
        result.Message = "订单不存在";
        return result;
      }
      var orderDto = order.MapTo<SaleOrderDto>();

      // ems配置信息
      var emsConfig = await parameterService.Value.GetValueAsync(EnumParameter.ems_config);
      var emsOptions = emsConfig.IsNullOrEmpty() ? null : JsonConvert.DeserializeObject<EMSClientOptions>(emsConfig);
      if (emsOptions == null || emsOptions.BaseUrl == null || emsOptions.SenderNo.IsNullOrEmpty() || emsOptions.Authorization.IsNullOrEmpty() || emsOptions.Key.IsNullOrEmpty()) {
        result.Message = "EMS配置信息不正确";
        return result;
      }

      // 获取面单号
      var emsResponse = await EMSHelper.CancelWayBillNoAsync(new M020006Request() {
        LogisticsOrderNo = orderDto.Code,
        WaybillNo = orderDto.DeliveryCode,
        CancelReason = cancelReason
      }, emsOptions);
      if (emsResponse.Code == 1) {
        result.Code = 1;
        orderDto.DeliveryCode = order.DeliveryCode = null;
        orderDto.DeliveryStatus = null;
        await _saleOrderRepository.UpdateAsync(order);
        result.Data = orderDto;
      } else {
        result.Message = emsResponse.Message;
      }

      return result;
    }

    #endregion

    #region 商品id是否被使用了

    /// <summary>
    /// 商品id是否被使用了
    /// </summary>
    /// <param name="productId"></param>
    /// <returns></returns>
    public async Task<bool> IsProductUserdAsync(int productId) {
      return await _saleOrderDetailRepository.AnyAsync(x => x.ProductId == productId);
    }

    #endregion

    #region 自提点是否被使用了

    /// <summary>
    /// 自提点是否被使用了
    /// </summary>
    /// <param name="selfOrgId"></param>
    /// <returns></returns>
    public async Task<bool> IsSelfOrgUsedAsync(int selfOrgId) {
      return await _saleOrderRepository.AnyAsync(x => x.SelfOrgId == selfOrgId);
    }

    #endregion

    #region 批量反打印

    /// <summary>
    /// 批量反打印
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    public async Task<AjaxResponse<List<SaleOrderDto>>> UnPrintBatchAsync(List<string> ids) {
      var result = new AjaxResponse<List<SaleOrderDto>>() {
        Code = 0
      };

      var orderList = await this.GetOrderListByIdsAsync(ids);

      if (orderList.Any(x => x.Status != (int) EnumSaleOrderStatus.已打印)) {
        result.Message = $"请选择 {EnumSaleOrderStatus.已打印} 的记录";
        return result;
      }

      // update
      foreach (var row in orderList) {
        row.Status = (int) EnumSaleOrderStatus.已审核;
      }
      await _saleOrderRepository.UpdateRangeAsync(orderList);

      // return
      result.Code = 1;
      result.Data = orderList.MapTo<List<SaleOrderDto>>();
      return result;
    }

    #endregion

    #region 放入回收站

    /// <summary>
    /// 放入回收站
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    public async Task<AjaxResponse<List<SaleOrderDto>>> RecycleBatchAsync(List<string> ids) {
      var result = new AjaxResponse<List<SaleOrderDto>>() {
        Code = 0
      };

      var orderList = await this.GetOrderListByIdsAsync(ids);

      if (orderList.Any(x => x.Status != (int) EnumSaleOrderStatus.未审核)) {
        result.Message = $"请选择 {EnumSaleOrderStatus.未审核} 的记录";
        return result;
      }

      // update
      foreach (var row in orderList) {
        row.Status = (int) EnumSaleOrderStatus.已删除;
      }
      await _saleOrderRepository.UpdateRangeAsync(orderList);

      // return
      result.Code = 1;
      result.Data = orderList.MapTo<List<SaleOrderDto>>();
      return result;
    }

    #endregion

    #region 移出回收站

    /// <summary>
    /// 移出回收站
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    public async Task<AjaxResponse<List<SaleOrderDto>>> UnRecycleBatchAsync(List<string> ids) {
      var result = new AjaxResponse<List<SaleOrderDto>>() {
        Code = 0
      };

      var orderList = await this.GetOrderListByIdsAsync(ids);

      if (orderList.Any(x => x.Status != (int) EnumSaleOrderStatus.已删除)) {
        result.Message = $"请选择 {EnumSaleOrderStatus.已删除} 的记录";
        return result;
      }

      // update
      foreach (var row in orderList) {
        row.Status = (int) EnumSaleOrderStatus.未审核;
      }
      await _saleOrderRepository.UpdateRangeAsync(orderList);

      // return
      result.Code = 1;
      result.Data = orderList.MapTo<List<SaleOrderDto>>();
      return result;
    }

    #endregion

    #region 重刷商品重量

    /// <summary>
    /// 重刷商品重量
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    public async Task<List<SaleOrderDto>> RefreshWeightAsync(List<string> ids) {
      // 查询主表
      var orderList = await this.GetOrderListByIdsAsync(ids);
      var detailList = await this.GetDetailListByIdsAsync(ids);

      // 商品档案
      var productIdList = detailList.Select(x => x.ProductId).Distinct().ToList();
      var productList = (await productService.Value.GetListByIdsAsync(productIdList)).ToLookup(x => x.Id);

      // 更新明细表
      foreach (var detail in detailList) {
        var product = productList[detail.ProductId].FirstOrDefault();
        detail.Weight = product?.Weight ?? decimal.Zero;
        detail.TotalWeight = detail.Qty * detail.Weight;
      }

      // 更新主表
      var detailDic = detailList.ToLookup(x => x.OrderId);
      foreach (var order in orderList) {
        order.GoodsWeight = detailDic[order.Id].Sum(x => x.TotalWeight);
      }

      try {
        _unitOfWork.BeginTransaction();
        await _saleOrderRepository.UpdateRangeAsync(orderList);
        await _saleOrderDetailRepository.UpdateRangeAsync(detailList);
        await _unitOfWork.CommitTransactionAsync();
      } catch {
        _unitOfWork.RollbackTransaction();
        throw;
      }

      return orderList.MapTo<List<SaleOrderDto>>();
    }

    #endregion

    #region 打印完毕后更新状态及数量

    /// <summary>
    /// 打印完毕后更新状态及数量
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    public async Task<List<SaleOrderDto>> UpdateStatusAfterPrintAsync(List<string> ids) {
      // 查询主表
      var orderList = await this.GetOrderListByIdsAsync(ids);

      foreach (var order in orderList) {
        // 未审核，不处理
        if (order.Status == (int) EnumSaleOrderStatus.未审核) {
          continue;
        }

        if (EnumSaleOrderStatusList.已审核.Contains(order.Status)) {
          order.Status = (int) EnumSaleOrderStatus.已打印;
        }

        order.PrintNum += 1;
      }

      await _saleOrderRepository.UpdateRangeAsync(orderList);
      return orderList.MapTo<List<SaleOrderDto>>();
    }

    #endregion

    #region 合并订单

    /// <summary>
    /// 查找可合并的订单
    /// </summary>
    /// <returns></returns>
    public async Task<List<SaleOrderDto>> FindMergeableOrdersAsync() {
      // 查询所有未审核的正常订单
      var query = from order in _saleOrderRepository.TableUntracked
                  where order.Status == (int)EnumSaleOrderStatus.未审核
                  select order;

      var orders = await query.ToListAsync();
      
      // 按收件地址、手机号、自提点进行分组
      var groupedOrders = orders.GroupBy(o => new {
        RecipientAddress = o.RecipientAddress?.Trim(),
        RecipientPhone = o.RecipientPhone?.Trim(), 
        SelfOrgId = o.SelfOrgId
      })
      .Where(g => g.Count() > 1) // 只返回有多个订单的分组
      .SelectMany(g => g) // 展开所有可合并的订单
      .OrderBy(o => o.RecipientAddress)
      .ThenBy(o => o.RecipientPhone)
      .ThenBy(o => o.SelfOrgName)
      .ThenBy(o => o.Code)
      .ToList();

      return groupedOrders.MapTo<List<SaleOrderDto>>();
    }

    /// <summary>
    /// 合并订单
    /// </summary>
    /// <param name="orderIds">要合并的订单ID列表</param>
    /// <returns></returns>
    public async Task<AjaxResponse<SaleOrderDto>> MergeOrdersAsync(List<string> orderIds) {
      var result = new AjaxResponse<SaleOrderDto>();
      
      if (orderIds == null || orderIds.Count < 2) {
        result.Code = 0;
        result.Message = "至少需要选择2个订单进行合并";
        return result;
      }

         
        try {
                _unitOfWork.BeginTransaction();
                // 获取要合并的订单
                var orders = await _saleOrderRepository.FindAsync(o => orderIds.Contains(o.Id));
          var orderList = orders.OrderBy(o => o.Code).ToList();
          
          // 验证订单状态
          var invalidOrders = orderList.Where(o => o.Status != (int)EnumSaleOrderStatus.未审核 || o.MainOrderFlag != (int)EnumMainOrderFlag.正常).ToList();
          if (invalidOrders.Any()) {
            result.Code = 0;
            result.Message = $"存在已审核或非正常状态的订单，无法合并：{string.Join(", ", invalidOrders.Select(o => o.Code))}";
            return result;
          }
          
          // 验证订单是否可以合并（收件地址、手机号、自提点相同）
          var firstOrder = orderList.First();
          var incompatibleOrders = orderList.Where(o => 
            o.RecipientAddress?.Trim() != firstOrder.RecipientAddress?.Trim() ||
            o.RecipientPhone?.Trim() != firstOrder.RecipientPhone?.Trim() ||
            o.SelfOrgId != firstOrder.SelfOrgId).ToList();
            
          if (incompatibleOrders.Any()) {
            result.Code = 0;
            result.Message = "选中的订单收件地址、手机号或自提点不完全相同，无法合并";
            return result;
          }

          // 选择第一个订单作为主订单
          var mainOrder = firstOrder;
          var otherOrders = orderList.Skip(1).ToList();
          
          // 获取所有订单的明细
          var allDetails = new List<SaleOrderDetail>();
          foreach (var order in orderList) {
            var details = await _saleOrderDetailRepository.FindAsync(d => d.OrderId == order.Id);
            allDetails.AddRange(details);
          }
          
          // 按商品ID分组，合并相同商品的数量
          var mergedDetails = allDetails.GroupBy(d => d.ProductId)
            .Select(g => {
              var firstDetail = g.First();
              return new SaleOrderDetail {
                Id = Guid.NewGuid().ToString(),
                OrderId = mainOrder.Id,
                ProductId = firstDetail.ProductId,
                ProductName = firstDetail.ProductName,
                SeqNo = firstDetail.SeqNo,
                Qty = g.Sum(d => d.Qty), // 合并数量
                Weight = firstDetail.Weight,
                TotalWeight = g.Sum(d => d.TotalWeight), // 合并重量
                GroupDetailId = string.Join(";", g.Where(d => !string.IsNullOrEmpty(d.GroupDetailId)).Select(d => d.GroupDetailId).Distinct())
              };
            }).ToList();
          
          // 更新主订单信息
          mainOrder.GoodsCount = mergedDetails.Count; // 商品品项数
          mainOrder.GoodsWeight = mergedDetails.Sum(d => d.TotalWeight); // 商品总重量
          mainOrder.GoodsAmt = otherOrders.Sum(o => o.GoodsAmt) + mainOrder.GoodsAmt; // 合并商品金额
          
          // 删除原有明细
          var existingDetails = await _saleOrderDetailRepository.FindAsync(d => d.OrderId == mainOrder.Id);
          await _saleOrderDetailRepository.RemoveRangeAsync(existingDetails);
          
          // 添加合并后的明细
          await _saleOrderDetailRepository.AddRangeAsync(mergedDetails);
          
          // 删除其他订单及其明细
          foreach (var order in otherOrders) {
            var details = await _saleOrderDetailRepository.FindAsync(d => d.OrderId == order.Id);
            await _saleOrderDetailRepository.RemoveRangeAsync(details);
            
            var paths = await _SaleOrderPathRepository.FindAsync(p => p.OrderId == order.Id);
            await _SaleOrderPathRepository.RemoveRangeAsync(paths);
          }
          await _saleOrderRepository.RemoveRangeAsync(otherOrders);
          
          // 更新主订单
          await _saleOrderRepository.UpdateAsync(mainOrder);
          
          // 添加操作记录
          var pathRecord = new SaleOrderPath {
            Id = Guid.NewGuid().ToString(),
            OrderId = mainOrder.Id,
            OpTime = DateTime.Now,
            OpCode = "MERGE",
            OpName = "订单合并",
            OpDesc = $"合并了 {otherOrders.Count} 个订单：{string.Join(", ", otherOrders.Select(o => o.Code))}",
            OperatorNo = "SYSTEM",
            OperatorName = "系统"
          };
          await _SaleOrderPathRepository.AddAsync(pathRecord);

              await  _unitOfWork.CommitTransactionAsync();
          
          result.Code = 1;
          result.Message = "订单合并成功";
          result.Data = mainOrder.MapTo<SaleOrderDto>();
          
        } catch (Exception ex) {
          _unitOfWork.RollbackTransaction();
          result.Code = 0;
          result.Message = $"订单合并失败：{ex.Message}";
        }
      
      
      return result;
    }

    #endregion

    #region 辅助方法

    /// <summary>
    /// 去除括号及其中的内容
    /// </summary>
    /// <param name="text">原始文本</param>
    /// <returns>去除括号后的文本</returns>
    private string RemoveParenthesesContent(string text) {
      if (string.IsNullOrWhiteSpace(text)) {
        return text;
      }

      // 去除中文括号及其中的内容
      var result = System.Text.RegularExpressions.Regex.Replace(text, "（[^）]*）", string.Empty);
      // 去除英文括号及其中的内容
      result = System.Text.RegularExpressions.Regex.Replace(result, "\\([^)]*\\)", string.Empty);
      
      return result.Trim();
    }

    #endregion

  }
}
